package org.sg20.parsename;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;


public class TrieTree {
    private final TrieNode root;

    public TrieTree(String whichmap) {
        root = new TrieNode(whichmap, false);
    }

    // Return false if the node exists.
    // If the word is short, the inserting or searching time is O(1).
    public boolean insertWord(String s) {
        boolean contain = true;

        TrieNode cur = root;
        //iter, each get the proceeding char using insertChild of TrieNode.
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (cur.insertChild(c, i == s.length() - 1))
                contain = false;
            cur = cur.getChild(c);
        }
        //if the trie tree contains the word, return false!!!
        return !contain;
    }

    public static class TrieNode {
        // children node
        private final Map<Character, TrieNode> children;
        private boolean isend;

        String whichmap;


        public TrieNode(String whichm, boolean ise) {
            whichmap = whichm;
            if (whichmap.equals("HashMap")) {
                children = new HashMap<>();
            } else if (whichmap.equals("TreeMap")) {
                children = new TreeMap<>();
            } else {
                children = new HashMap<>();
            }
            isend = ise;
        }


        public void setEnd() {
            isend = true;
        }

        public boolean isEnd() {
            return isend;
        }

        //public boolean containChild(char c){return children.containsKey(c);}

        public TrieNode getChild(char c) {
            if (!children.containsKey(c))
                return null;
            return children.get(c);
        }

        public boolean insertChild(char c, boolean ise) {
            // child is not END but the node to be inserted is END, we will change the mode.
            if (children.containsKey(c) && !(!children.get(c).isEnd() && ise))
                return false;

            if (!children.containsKey(c))
                children.put(c, new TrieNode(whichmap, ise));
            else if (ise) //child is END but the node to be inserted is not END
                children.get(c).setEnd();
            return true;
        }
    }

    public TrieNode getRoot(){
        return root;
    }

}